/**
 *  deferredconsumerbase.h
 *
 *  Base class for the deferred consumer and the
 *  deferred get.
 *
 *  @copyright 2016 Copernica B.V.
 */

/**
 *  Include guard
 */
#pragma once

/**
 *  Dependencies
 */
#include "deferredmessage.h"

/**
 *  Start namespace
 */
namespace AMQP {

/**
 *  Forward declarations
 */
class BasicDeliverFrame;
class BasicGetOKFrame;

/**
 *  Base class for deferred consumers
 */
class DeferredConsumerBase :
    public DeferredMessage,
    public std::enable_shared_from_this<DeferredConsumerBase>
{
private:
    /**
     *  Process a delivery frame
     *
     *  @param  frame   The frame to process
     */
    void process(BasicDeliverFrame &frame);

    /**
     *  Process a delivery frame from a get request
     *
     *  @param  frame   The frame to process
     */
    void process(BasicGetOKFrame &frame);

    /**
     *  Indicate that a message was done
     */
    virtual void complete();

    /**
     *  Emit a message
     *
     *  @param  message     The message to emit
     *  @param  deliveryTag The delivery tag (for ack()ing)
     *  @param  redelivered Is this a redelivered message
     */
    virtual void emit(Message &&message, uint64_t deliveryTag, bool redelivered) const = 0;

    /**
     *  Frames may be processed
     */
    friend class ChannelImpl;
    friend class BasicDeliverFrame;
    friend class BasicGetOKFrame;
protected:
    /**
     *  The delivery tag for the current message
     *  @var    uint64_t
     */
    uint64_t _deliveryTag = 0;

    /**
     *  Is this a redelivered message
     *  @var    bool
     */
    bool _redelivered = false;

    /**
     *  The channel to which the consumer is linked
     *  @var    ChannelImpl
     */
	std::weak_ptr<ChannelImpl> _channel;

    /**
     *  Callback for new message
     *  @var    BeginCallback
     */
    BeginCallback _beginCallback;

	/**
	*  Callback for incoming messages
	*  @var    MessageCallback
	*/
	MessageCallback _messageCallback;

    /**
     *  Callback for when a message was complete finished
     *  @var    CompleteCallback
     */
    CompleteCallback _completeCallback;

    /**
     *  Constructor
     *
     *  @param  failed  Have we already failed?
     *  @param  channel The channel we are consuming on
     */
	DeferredConsumerBase(bool failed, std::weak_ptr<ChannelImpl> channel) : DeferredMessage(failed), _channel(channel) {}
public:
};

/**
 *  End namespace
 */
}
